home *** CD-ROM | disk | FTP | other *** search
/ NOVA - For the NeXT Workstation / NOVA - For the NeXT Workstation.iso / Apps / ArchiveUtils / nx_arc / arcio.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-12-20  |  7.8 KB  |  303 lines

  1. /*
  2.  * $Log:    arcio.c,v $
  3.  * Revision 1.2  88/04/11  18:01:16  hyc
  4.  * added support for squashing. (changed max hdrver from 8 to 9)
  5.  * 
  6.  * Revision 1.1  88/04/11  17:59:43  hyc
  7.  * Initial revision
  8.  * 
  9.  * Revision 1.3  87/12/19  04:25:24  hyc
  10.  * As before, different location tho.
  11.  * 
  12.  * Revision 1.2  87/12/19  04:23:21  hyc
  13.  * Fix problem caused by indent(?) screwing up line boundaries...
  14.  * 
  15.  * Revision 1.1  87/12/19  04:21:23  hyc
  16.  * Initial revision
  17.  * 
  18.  * Revision 1.4  87/08/13  17:03:24  hyc
  19.  * Run thru the indent program...
  20.  *  Revision 1.3  87/07/21  11:41:29  hyc *** empty
  21.  * log message ***
  22.  * 
  23.  * Revision 1.2  87/07/21  08:19:45  hyc *** empty log message ***
  24.  * 
  25.  */
  26.  
  27. /*
  28.  * ARC - Archive utility - ARCIO
  29.  * 
  30.  * Version 2.49, created on 07/25/86 at 16:44:23
  31.  * 
  32.  * (C) COPYRIGHT 1985,86 by System Enhancement Associates; ALL RIGHTS RESERVED
  33.  * 
  34.  * By:  Thom Henderson
  35.  * 
  36.  * Description: This file contains the file I/O routines used to manipulate an
  37.  * archive.
  38.  * 
  39.  * Language: Computer Innovations Optimizing C86
  40.  */
  41. #include <stdio.h>
  42. #include "arc.h"
  43.  
  44. INT
  45. readhdr(hdr, f)            /* read a header from an archive */
  46.     struct heads   *hdr;    /* storage for header */
  47.     FILE           *f;    /* archive to read header from */
  48. {
  49. #ifndef MSDOS
  50.     unsigned char   dummy[28];
  51.     INT             i, j, k;
  52. #endif
  53.     char            name[13];    /* filename buffer */
  54.     INT             try = 0;/* retry counter */
  55.     static INT      first = 1;    /* true only on first read */
  56.  
  57.     if (!f)            /* if archive didn't open */
  58.         return 0;    /* then pretend it's the end */
  59.     if (feof(f))        /* if no more data */
  60.         return 0;    /* then signal end of archive */
  61.  
  62.     if (fgetc(f) != 26) {    /* check archive validity */
  63.         if (warn) {
  64.             printf("An entry in %s has a bad header.", arcname);
  65.             nerrs++;
  66.         }
  67.         while (!feof(f)) {
  68.             try++;
  69.             if (fgetc(f) == 26) {
  70.                 ungetc(hdrver = fgetc(f), f);
  71.                 if (hdrver >= 0 && hdrver <= 9)
  72.                     break;
  73.             }
  74.         }
  75.  
  76.         if (feof(f) && first)
  77.             arc_abort("%s is not an archive", arcname);
  78.  
  79.         if (warn)
  80.             printf("  %d bytes skipped.\n", try);
  81.  
  82.         if (feof(f))
  83.             return 0;
  84.     }
  85.     hdrver = fgetc(f);    /* get header version */
  86.     if (hdrver < 0)
  87.         arc_abort("Invalid header in archive %s", arcname);
  88.     if (hdrver == 0)
  89.         return 0;    /* note our end of archive marker */
  90.     if (hdrver > 9) {
  91.         fread(name, sizeof(char), 13, f);
  92. #ifdef MTS
  93.         atoe(name, strlen(name));
  94. #endif
  95.         printf("I don't know how to handle file %s in archive %s\n",
  96.                name, arcname);
  97.         printf("I think you need a newer version of ARC.\n");
  98.         exit(1);
  99.     }
  100.     /* amount to read depends on header type */
  101.  
  102.     if (hdrver == 1) {    /* old style is shorter */
  103.         fread(hdr, sizeof(struct heads) - sizeof(long int), 1, f);
  104.         hdrver = 2;    /* convert header to new format */
  105.         hdr->length = hdr->size;    /* size is same when not
  106.                          * packed */
  107.     } else
  108. #ifdef MSDOS
  109.         fread(hdr, sizeof(struct heads), 1, f);
  110. #else
  111.         fread(dummy, 27, 1, f);
  112.  
  113.     for (i = 0; i < 13; hdr->name[i] = dummy[i], i++);
  114. #ifdef MTS
  115.     (void) atoe(hdr->name, strlen(hdr->name));
  116. #endif
  117.     hdr->size = (LONG) ((dummy[16] << 24) + (dummy[15] << 16) + (dummy[14] << 8)
  118.                 + dummy[13]);
  119.     hdr->date = (short) ((dummy[18] << 8) + dummy[17]);
  120.     hdr->time = (short) ((dummy[20] << 8) + dummy[19]);
  121.     hdr->crc = (short) ((dummy[22] << 8) + dummy[21]);
  122.     hdr->length = (LONG) ((dummy[26] << 24) + (dummy[25] << 16)
  123.                   + (dummy[24] << 8) + dummy[23]);
  124. #endif
  125.  
  126.     if (hdr->date > olddate
  127.         || (hdr->date == olddate && hdr->time > oldtime)) {
  128.         olddate = hdr->date;
  129.         oldtime = hdr->time;
  130.     }
  131.     first = 0;
  132.     return 1;        /* we read something */
  133. }
  134.  
  135. put_int(number, f)        /* write a 2 byte integer */
  136.     INT             number;
  137.     FILE           *f;
  138. {
  139.     fputc(number & 255, f);
  140.     fputc(number >> 8, f);
  141. }
  142.  
  143. put_long(number, f)        /* write a 4 byte integer */
  144.     LONG            number;
  145.     FILE           *f;
  146. {
  147.     put_int(number & 0xFFFF, f);
  148.     put_int(number >> 16, f);
  149. }
  150.  
  151. INT
  152. writehdr(hdr, f)        /* write a header to an archive */
  153.     struct heads   *hdr;    /* header to write */
  154.     FILE           *f;    /* archive to write to */
  155. {
  156.     fputc(26, f);        /* write out the mark of ARC */
  157.     fputc(hdrver, f);    /* write out the header version */
  158.     if (!hdrver)        /* if that's the end */
  159.         return;        /* then write no more */
  160. #ifdef MSDOS
  161.     fwrite(hdr, sizeof(struct heads), 1, f);
  162. #else
  163.     /* byte/word ordering hassles... */
  164. #ifdef MTS
  165.     etoa(hdr->name, strlen(hdr->name));
  166. #endif
  167.     fwrite(hdr->name, 1, 13, f);
  168.     put_long(hdr->size, f);
  169.     put_int(hdr->date, f);
  170.     put_int(hdr->time, f);
  171.     put_int(hdr->crc, f);
  172.     put_long(hdr->length, f);
  173. #endif
  174.  
  175.     /* note the newest file for updating the archive timestamp */
  176.  
  177.     if (hdr->date > arcdate
  178.         || (hdr->date == arcdate && hdr->time > arctime)) {
  179.         arcdate = hdr->date;
  180.         arctime = hdr->time;
  181.     }
  182. }
  183.  
  184. INT
  185. putc_tst(c, t)            /* put a character, with tests */
  186.     char            c;    /* character to output */
  187.     FILE           *t;    /* file to write to */
  188. {
  189.     if (t)
  190. #ifdef BSD
  191.         fputc(c, t);
  192. #else
  193.         if (fputc(c, t) == EOF)
  194.             arc_abort("Write fail (disk full?)");
  195. #endif
  196. }
  197.  
  198. /*
  199.  * NOTE:  The filecopy() function is used to move large numbers of bytes from
  200.  * one file to another.  This particular version has been modified to improve
  201.  * performance in Computer Innovations C86 version 2.3 in the small memory
  202.  * model.  It may not work as expected with other compilers or libraries, or
  203.  * indeed with different versions of the CI-C86 compiler and library, or with
  204.  * the same version in a different memory model.
  205.  * 
  206.  * The following is a functional equivalent to the filecopy() routine that
  207.  * should work properly on any system using any compiler, albeit at the cost
  208.  * of reduced performance:
  209.  * 
  210.  * filecopy(f,t,size) 
  211.  *      FILE *f, *t; long size; 
  212.  * { 
  213.  *      while(size--)
  214.  *              putc_tst(fgetc(f),t); 
  215.  * }
  216.  */
  217. #ifdef MSDOS
  218. #include <fileio2.h>
  219.  
  220. filecopy(f, t, size)        /* bulk file copier */
  221.     FILE           *f, *t;    /* files from and to */
  222.     long            size;    /* bytes to copy */
  223. {
  224.     char           *buf;    /* buffer pointer */
  225.     char           *alloc();/* buffer allocator */
  226.     unsigned int    bufl;    /* buffer length */
  227.     unsigned int    coreleft();    /* space available reporter */
  228.     unsigned int    cpy;    /* bytes being copied */
  229.     long            floc, tloc, fseek();    /* file pointers, setter */
  230.     struct regval   reg;    /* registers for DOS calls */
  231.  
  232.     if ((bufl = coreleft()) < 1000)    /* see how much space we have */
  233.         arc_abort("Out of memory");
  234.     bufl -= 1000;        /* fudge factor for overhead */
  235.     if (bufl > 60000)
  236.         bufl = 60000;    /* avoid choking alloc() */
  237.     if (bufl > size)
  238.         bufl = size;    /* avoid wasting space */
  239.     buf = alloc(bufl);    /* allocate our buffer */
  240.  
  241.     floc = fseek(f, 0L, 1);    /* reset I/O system */
  242.     tloc = fseek(t, 0L, 1);
  243.  
  244.     segread(®.si);    /* set segment registers for DOS */
  245.  
  246.     while (size > 0) {    /* while more to copy */
  247.         reg.ax = 0x3F00;/* read from handle */
  248.         reg.bx = filehand(f);
  249.         reg.cx = bufl < size ? bufl : size;    /* amount to read */
  250.         reg.dx = buf;
  251.         if (sysint21(®, ®) & 1)
  252.             arc_abort("Read fail");
  253.  
  254.         cpy = reg.ax;    /* amount actually read */
  255.         reg.ax = 0x4000;/* write to handle */
  256.         reg.bx = filehand(t);
  257.         reg.cx = cpy;
  258.         reg.dx = buf;
  259.         sysint21(®, ®);
  260.  
  261.         if (reg.ax != cpy)
  262.             arc_abort("Write fail (disk full?)");
  263.  
  264.         size -= (long) cpy;
  265.     }
  266.  
  267.     free(buf);        /* all done with buffer */
  268. }
  269. #else
  270.  
  271. filecopy(f, t, size)        /* bulk file copier */
  272.     FILE           *f, *t;    /* files from and to */
  273.     LONG            size;    /* bytes to copy */
  274. {
  275.     char           *buf;    /* buffer pointer */
  276.     char           *malloc();    /* buffer allocator */
  277.     unsigned int    bufl;    /* buffer length */
  278.     unsigned int    cpy;    /* bytes being copied */
  279. #ifdef MTS
  280. #define MTEXT    0x0010
  281. #endif
  282.  
  283.     bufl = 60000;
  284.     if (bufl > size)
  285.         bufl = size;    /* don't waste space */
  286.  
  287.     buf = malloc(bufl);
  288.  
  289.     while (size > 0) {
  290.         cpy = fread(buf, sizeof(char), bufl < size ? bufl : size, f);
  291. #ifdef MTS
  292.         if ((f->_fmode & MTEXT) && !image)
  293.             etoa(buf, cpy);
  294. #endif
  295.         if (fwrite(buf, sizeof(char), cpy, t) != cpy)
  296.             arc_abort("Write fail (no space?)");
  297.         size -= cpy;
  298.     }
  299.  
  300.     free(buf);
  301. }
  302. #endif
  303.